﻿//written by ahmed fathi

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Specialized;
using dtSearch.Engine;

namespace DTSearchHelper
{
    public class IndexHelper
    {

        #region constructors
        //==============================================================================
        public IndexHelper()
        {
        }
        //==============================================================================
        #endregion

        #region fields & properties

        //delgetes and events
        public delegate void IndexFinishedDelegate(object sender, IndexHelperEventArgs e);
        public event IndexFinishedDelegate IndexFinished;

        private delegate bool IndexDelegate();


        //Indexjob object
        private IndexJob indexJobObject = new IndexJob();
        public IndexJob IndexJobObject
        {
            get { return indexJobObject; }
        }

        //index Path
        private string indexPath = "";
        public string IndexPath
        {
            get { return indexPath; }
            set { indexPath = value; }
        }


        //flag to abort Indexing
        private bool abortIndexing = false;
        public bool AbortIndex
        {
            get { return abortIndexing; }
            set
            {
                abortIndexing = value;
            }
        }


        private bool compress = false;
        public bool Compress
        {
            get { return compress; }
            set { compress = value; }
        }

        private bool reIndex = false;
        public bool ReIndex
        {
            get { return reIndex; }
            set { reIndex = value; }
        }


        string listTODeletedPath = "";
        public string ListTODeletedPath
        {
            get { return listTODeletedPath; }
            set { listTODeletedPath = value; }
        }


        private DataSource dataSourceToIndex = null;
        public DataSource DataSourceToIndex
        {
            get { return dataSourceToIndex; }
            set { dataSourceToIndex = value; }
        }

       
        #endregion
        
        #region methods

        //begin Index
        public void beginIndexing(SortedList<string, object> OtherInformation)
        {
            this.abortIndexing = false;

            this.indexJobObject = new IndexJob();
            this.indexJobObject.IndexPath = this.indexPath;
            this.indexJobObject.ActionAdd = true;
            this.indexJobObject.ActionCreate = this.reIndex;
            this.indexJobObject.ActionCompress = this.compress;
            if (this.listTODeletedPath.Trim() != "")
            {
                this.indexJobObject.ActionRemoveListed = true;
                this.indexJobObject.ToRemoveListName = this.listTODeletedPath;
            }
            this.indexJobObject.DataSourceToIndex = this.dataSourceToIndex;


            IndexDelegate m = new IndexDelegate(this.IndexJobObject.Execute);
            m.BeginInvoke(new AsyncCallback(this.finish), OtherInformation);
        }

        public void beginIndexing(SortedList<string, object> OtherInformation, IndexStatusHandler IndexStatusHandler)
        {

            this.abortIndexing = false;

            this.indexJobObject = new IndexJob();
            this.indexJobObject.IndexPath = this.indexPath;
            this.indexJobObject.ActionAdd = true;
            this.indexJobObject.ActionCreate = this.reIndex;
            this.indexJobObject.ActionCompress = this.compress;
            if (this.listTODeletedPath.Trim() != "")
            {
                this.indexJobObject.ActionRemoveListed = true;
                this.indexJobObject.ToRemoveListName = this.listTODeletedPath;
            }
            this.indexJobObject.DataSourceToIndex = this.dataSourceToIndex;
            this.indexJobObject.StatusHandler = IndexStatusHandler;

            IndexDelegate m = new IndexDelegate(this.IndexJobObject.Execute);
            m.BeginInvoke(new AsyncCallback(this.finish), OtherInformation);
        }

        //Index
        public IndexHelperEventArgs Index(SortedList<string, object> OtherInformation)
        {

            this.abortIndexing = false;

            this.indexJobObject = new IndexJob();
            this.indexJobObject.IndexPath = this.indexPath;
            this.indexJobObject.ActionAdd = true;
            this.indexJobObject.ActionCreate = this.reIndex;
            this.indexJobObject.ActionCompress = this.compress;
            if (this.listTODeletedPath.Trim() != "")
            {
                this.indexJobObject.ActionRemoveListed = true;
                this.indexJobObject.ToRemoveListName = this.listTODeletedPath;
            }
            this.indexJobObject.DataSourceToIndex = this.dataSourceToIndex;

            this.IndexJobObject.Execute();

            JobErrorInfo jobErrors = (JobErrorInfo)this.IndexJobObject.Errors;
            List<ErrorHelper> errors = new List<ErrorHelper>();
            for (int i = 0; i < jobErrors.Count; i++)
            {
                if ((int)jobErrors.Code(i) != 120)
                {
                    errors.Add(new ErrorHelper((int)jobErrors.Code(i)));
                }
            }
            IndexHelperEventArgs DTIndexEventArgs = new IndexHelperEventArgs(this, errors, OtherInformation);
            return DTIndexEventArgs;
        }


        public IndexHelperEventArgs Index(SortedList<string, object> OtherInformation, IndexStatusHandler IndexStatusHandler)
        {
            this.abortIndexing = false;

            this.indexJobObject = new IndexJob();
            this.indexJobObject.IndexPath = this.indexPath;
            this.indexJobObject.ActionAdd = true;
            this.indexJobObject.ActionCreate = this.reIndex;
            this.indexJobObject.ActionCompress = this.compress;
            if (this.listTODeletedPath.Trim() != "")
            {
                this.indexJobObject.ActionRemoveListed = true;
                this.indexJobObject.ToRemoveListName = this.listTODeletedPath;
            }
            this.indexJobObject.DataSourceToIndex = this.dataSourceToIndex;
            this.indexJobObject.StatusHandler = IndexStatusHandler;

            this.IndexJobObject.Execute();

            JobErrorInfo jobErrors = (JobErrorInfo)this.IndexJobObject.Errors;
            List<ErrorHelper> errors = new List<ErrorHelper>();
            for (int i = 0; i < jobErrors.Count; i++)
            {
                if ((int)jobErrors.Code(i) != 120)
                {
                    errors.Add(new ErrorHelper((int)jobErrors.Code(i)));
                }
            }
            IndexHelperEventArgs DTIndexEventArgs = new IndexHelperEventArgs(this, errors, OtherInformation);
            return DTIndexEventArgs;
        }


        //finish Index
        private void finish(IAsyncResult IAsyncRes)
        {
            if (!this.abortIndexing)
            {
                JobErrorInfo jobErrors = (JobErrorInfo)this.IndexJobObject.Errors;
                List<ErrorHelper> errors = new List<ErrorHelper>();
                for (int i = 0; i < jobErrors.Count; i++)
                {
                    if ((int)jobErrors.Code(i) != 120)
                    {
                        errors.Add(new ErrorHelper((int)jobErrors.Code(i)));
                    }
                }
                if (this.IndexFinished != null)
                {
                    SortedList<string, object> otherInformation = (SortedList<string, object>)IAsyncRes.AsyncState;
                    IndexHelperEventArgs DTIndexEventArgs = new IndexHelperEventArgs(this, errors, otherInformation);
                    this.IndexFinished(this, DTIndexEventArgs);
                }
            }
        }


        //add spaces
        public static string AddSpaces(string statement)
        {
            statement = " " + statement + " ";
            statement = statement.Replace("(", " ( ")
            .Replace(")", " ) ")
            .Replace("\t", " ")
            .Replace("\r", " ")
            .Replace("\n", " ")
            .Replace(".", " ")
            .Replace(",", " ")
            .Replace("*", " ")
            .Replace("?", " ")
            .Replace("؟", " ")
            .Replace("~", " ")
            .Replace("(", " ")
            .Replace(")", " ");
            return statement;
        }

        //replace arabic letters in arabic satement
        public static string replaceArabicLetters(string statement, bool includeJoiners)
        {
            statement = IndexHelper.AddSpaces(statement);
            statement = statement.Replace("أ", "ا")
           .Replace("إ", "ا")
           .Replace("آ", "ا")
           .Replace("ة", "ه")
           .Replace("ى", "ي");
            if (includeJoiners)
            {
                statement = statement.Replace(" و ", " AND ")
               .Replace(" او ", " OR ")
               .Replace(" ليس ", " NOT ")
               .Replace(" وليس ", " AND NOT ")
               .Replace(" اوليس ", " OR NOT ");
            }
            return statement.Trim();
        }

        //to uni statement
        public static string ToUniCompStatement(string statement)
        {
            statement = IndexHelper.replaceArabicLetters(statement, true).ToLower();
            statement = statement.Replace(" ", "");
            return statement;
        }

        public static string removeSpaces(string statement, bool Remove_Abd_Space)
        {
            if (Remove_Abd_Space)
            {
                while (statement.Contains(" عبد "))
                {
                    statement = statement.Replace(" عبد ", " عبد");
                }
                while (statement.Contains(" ابو "))
                {
                    statement = statement.Replace(" ابو ", " ابو");
                }
            }
            while (statement.Contains("  "))
            {
                statement = statement.Replace("  ", " ");
            }
            statement = statement.Trim();
            return statement;
        }

        //prepare statement
        public static string PrepareStatement(string statement, bool convertArabicJoiner, bool Remove_Abd_Space)
        {
            statement = IndexHelper.replaceArabicLetters(statement, convertArabicJoiner);
            statement = IndexHelper.removeSpaces(statement, Remove_Abd_Space);
            return statement;
        }

        
        
        #endregion

    }



    public class IndexHelperEventArgs : EventArgs
    {
        private List<ErrorHelper> errors = null;
        public System.Collections.ObjectModel.ReadOnlyCollection<ErrorHelper> Errors
        {
            get { return errors.AsReadOnly(); }
        }

        private IndexHelper indexHelperObject = null;
        public IndexHelper IndexHelperObject
        {
            get
            {
                return this.indexHelperObject;
            }
        }

        private SortedList<string, object> otherInformation = null;
        public SortedList<string, object> OtherInformation
        {
            get { return otherInformation; }
        }

        public IndexHelperEventArgs(IndexHelper IndexHelperObject, List<ErrorHelper> errors, SortedList<string, object> otherInformation)
        {
            this.indexHelperObject = IndexHelperObject;
            this.errors = errors;
            this.otherInformation = otherInformation;
        }
    }

}
